#include "App.h"
#include <SFML\System.hpp>
#include <SFML\System\Clock.hpp>

void App::GameLoop(void)
  {
    SLOG(App_Loop, SeverityInfo) << std::endl;

    // Clock used in restricting Update loop to a fixed rate
    sf::Clock anUpdateClock;

    // Clock used in calculating the time elapsed since the last frame
    sf::Clock anFrameClock;

    // Restart/Reset our Update clock
    anUpdateClock.restart();

    // When do we need to update next (in milliseconds)?
    sf::Int32 anUpdateNext = anUpdateClock.getElapsedTime().asMilliseconds();

    // Make sure we have at least one state active
    if(mStateManager.IsEmpty())
    {
      // Exit with an error since there isn't an active state
      Quit(StatusAppInitFailed);
    }

    // Loop while IsRunning returns true
    while(IsRunning() && mWindow.isOpen() && !mStateManager.IsEmpty())
    {
      // Get the currently active state
      IState& anState = mStateManager.GetActiveState();

      // Count the number of sequential UpdateFixed loop calls
      Uint32 anUpdates = 0;

      // Process any available input
      ProcessInput(anState);

      // Make note of the current update time
      sf::Int32 anUpdateTime = anUpdateClock.getElapsedTime().asMilliseconds();

	  // Process our UpdateFixed portion of the game loop
      while((anUpdateTime - anUpdateNext) >= mUpdateRate && anUpdates++ < mMaxUpdates)
      {
        // Let the current active state perform fixed updates next
        anState.UpdateFixed();

        // Let the StatManager perfom its updates
        mStatManager.UpdateFixed();

        // Compute the next appropriate UpdateFixed time
        anUpdateNext += mUpdateRate;
      } // while((anUpdateTime - anUpdateNext) >= mUpdateRate && anUpdates <= mMaxUpdates)

      // Let the current active state perform its variable update

	  // Convert to floating point value of seconds for SFML 2.0
      anState.UpdateVariable(anFrameClock.restart().asSeconds());


      // Let the current active state draw stuff
      anState.Draw();

      // Let the StatManager perform its drawing
      mStatManager.Draw();

      // Display Render window to the screen
      mWindow.display();
      // Handle Cleanup of any recently removed states at this point as needed
      mStateManager.HandleCleanup(); 
    } // while(IsRunning() && !mStates.empty())
  }